import OrderUtil from "../utils";
import OrderClassOrders from '../class/Orders';
import OrderClassDetail from "../class/Detail";
import ParamsError from "../../lib/errors/ParamsError";
import OrderClassOrdersVersion from "../class/OrdersVersion";
import { identity } from "lodash";
import { OrdersIface } from '../iface/Order';
import { RSA } from "@ctsy/crypto";
import BaseController from "@ctsy/controller/dist/base_controller";
import { Op } from '@ctsy/model';

export default class Orders extends BaseController {
    /**
     * 添加订单
     * @param orderData 订单数据
     */
    async adds(orderData: OrderClassOrders | any) {
        //1. 校验:公共数据
        await this.validataorOrder(orderData, orderData.Goods)

        //2. 校验:订单
        if (orderData.OrderID) {
            throw new ParamsError("订单号应该为空")
        }
        //3. 校验:订单明细
        let orderDetailData = []
        for (const iterator of orderData.Goods) {
            if (iterator.LID) {
                throw new ParamsError("明细编号应该为空")
            }
            orderDetailData.push(iterator)
        }

        //4. 生成:订单版本数据
        let orderVersionData: any = new OrderClassOrdersVersion();
        for (const key in orderVersionData) {
            if (orderData[key]) {
                orderVersionData[key] = orderData[key]
            }
        }

        orderData.No = new Date().getTime();
        /**
         * 手动生成订单测试
         */
        // orderData.No = "test0006";

        //5. 保存数据库
        await this.startTrans();
        try {
            //1). 添加订单
            let sqOrderId = await this.M(OrdersIface.Orders).where({ No: orderData.No }).find()
            if (sqOrderId) {
                throw new Error("订单号不能重复");
            }
            delete orderData.Goods;
            sqOrderId = await this.M(OrdersIface.Orders).add(orderData)

            //2). 添加订单版本
            orderVersionData.OrderID = sqOrderId.OrderID
            let orderVersionOVID = await this.M(OrdersIface.OrdersVersion).add(orderVersionData)

            //3). 添加订单明细
            orderDetailData.forEach((value: any) => {
                value.OrderID = sqOrderId.OrderID
                value.V = orderVersionOVID.OVID
            })
            await this.M(OrdersIface.OrderDetail).addAll(orderDetailData)
            await this.commit();
            return sqOrderId
        } catch (error) {
            await this.rollback();
            throw error;
        }
    }
    /**
     * 删除订单
     * @param d 订单id
     */
    async del(d:{OrderID:number}) {
        if (!(d.OrderID > 0)) {
            throw new ParamsError("OrderID")
        }
        await this.startTrans();
        try {
           let rs
           await Promise.all([
                rs=this.M(OrdersIface.Orders).where({ OrderID: d.OrderID }).del(),
                this.M(OrdersIface.OrdersVersion).where({ OrderID: d.OrderID }).del(),
                this.M(OrdersIface.OrderDetail).where({ OrderID: d.OrderID }).del()
            ])
            await this.commit();
            return rs;
        } catch (error) {
            await this.rollback()
            throw error;
        }
    }
    /**
     * 修改订单
     * @param d 订单信息
     */
    async save(d: { DBOrder: any, DBOrderDetail: any, DBOrderVersion: any }) {
        //1. 校验:公共数据
        await this.validataorOrder(d.DBOrder, d.DBOrderDetail)
        if (!d.DBOrder.OrderID || !d.DBOrderDetail[0].LID || !d.DBOrderVersion.OVID) {
            throw new ParamsError("缺少订单参数")
        }

        //3.校验版本
        let validatorVersion = ["IsOutTrans", "IsInTrans"]
        OrderUtil.validataor(new OrderClassOrdersVersion, d.DBOrderVersion, validatorVersion)

        if (!await this.M(OrdersIface.Orders).where({ OrderID: d.DBOrder.OrderID }).find()) {
            throw new ParamsError(`数据表没有数据， ${d.DBOrder.OrderID}`);
        }
        if (!await this.M(OrdersIface.OrdersVersion).where({ OVID: d.DBOrderVersion.OVID }).find()) {
            throw new ParamsError(`数据表没有${d.DBOrderVersion.OVID}`);
        }

        await this.startTrans();
        try {
            await this.M(OrdersIface.OrderDetail).where({ OrderID: d.DBOrderDetail[0].OrderID }).del()
            // 添加
            let rs;
            await Promise.all([
                rs=this.M(OrdersIface.Orders).where({ OrderID: d.DBOrder.OrderID }).limit(1).save(d.DBOrder),
                this.M(OrdersIface.OrdersVersion).where({ OVID: d.DBOrderVersion.OVID }).limit(1).save(d.DBOrderVersion),
                this.M(OrdersIface.OrderDetail).addAll(d.DBOrderDetail)
            ])
            await this.commit();
            return rs;
        } catch (error) {
            await this.rollback()
            throw error;
        }
    }
    /**
     * 查询订单
     * @param d 订单id 版本
     */
    async get(d: { orderID: number, v: number }) {
        if (!(d.orderID > 0) || !(d.v > 0)) {
            throw new ParamsError("OrderID or V")
        }
        let rs = await this.R(OrdersIface.Orders).where({ OrderID: d.orderID, V: d.v }).find()
        if (!(Object.keys(rs).length > 0)) {
            throw new ParamsError("没有查询到对像")
        }
        return rs
    }
    /**
     * 分页查询 
     * @param Keyword 搜索关键字
     * @param P 页码
     * @param N 条数
     */
    async search({ Keyword, P, N }: { Keyword: string, [index: string]: any }) {
        let condition = Keyword == "" ? { OrderId: { gt: 1 } } : { No: Keyword }
        return await this.M(OrdersIface.Orders).where(condition).page(P || 1, N || 10).select()
    }

    /**
     * 订单共用检测器
     * @param order 订单数据
     * @param orderDetail 订单详情数据
     */
    async validataorOrder(order: OrderClassOrders, orderDetail: any | OrderClassDetail) {
        //1 校验：订单
        //  检测器:忽略校验字段
        let validataorOrder = ["OrderID", "Discount", "IsPushStore", "IsPushUnit", "IsPushLog"]
        OrderUtil.validataor(new OrderClassOrders, order, validataorOrder)
        if (order.FromType > 4 || order.Status > 14 || order.InType > 5 || order.OutType > 5) {
            throw new ParamsError("选择类型错误")
        }
        if (!order.No) {
            throw new ParamsError("订单号不能为空")
        }
        if (order.Settle != (order.Money - order.Discount) || order.Settle < 0) {
            throw new ParamsError("结算金额错误")
        }
        if (order.InUnitID != order.OutUnitID) {
            throw new ParamsError("入库单位与出库单位不符")
        }

        //2 校验:订单明细
        let validataDetail = ["LID", "BStock", "BTStock", "ATStock"];
        let detailData: any = [];
        let detailAmount: number = 0;
        let detailMoney: number = 0;
        for (const iterator of orderDetail) {
            OrderUtil.validataor(new OrderClassDetail, iterator, validataDetail)
            if (iterator.Batch == "") {
                throw new ParamsError("批次不能为空 ");
            }
            if (iterator.Amount > (iterator.BStock + iterator.BTStock)) {
                throw new ParamsError("交易量大于库存")
            }
            detailData.push(iterator);
            detailAmount += iterator.Amount;
            detailMoney += iterator.Money;
            console.log(iterator);
        }
        //3 校验:订单与订单明细关联
        if (detailAmount != order.Amount) {
            throw new ParamsError("订单明细总数与订单总数不符")
        }
        if (detailMoney != order.Money) {
            throw new ParamsError("订单明细金额下订单金额不符")
        }
        //4 返回
        return detailData;
    }
}